package com.example.ccj.u.sqlite;

import android.content.ContentValues;
import android.util.Pair;

import androidx.annotation.NonNull;

import com.alibaba.fastjson.JSON;
import com.example.ccj.u.LogUtils;
import com.example.ccj.u.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Reflection {
    private static final String TAG = "Reflection";

    public static String getTableName(Class<?> cls){
        Object obj = null;
        try {
            obj = cls.newInstance();
            TableName tableName = obj.getClass().getAnnotation(TableName.class);
            if (tableName != null) {
                String value = tableName.value();
                if (!StringUtils.isEmpty(value)) {
                    return value;
                }
            } else {
                throw new RuntimeException("要获取数据的表需要添加TableName注释");
            }
        } catch (IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Pair<String,List<TableBean>> getBeanTableFieldData(@NonNull Class<?> cls) throws IllegalAccessException, InstantiationException {
        TableName tableNameInter = cls.getAnnotation(TableName.class);
        List<TableBean> tableBeans = new ArrayList<>();
        String tableName = null;
        if (tableNameInter != null) {
            tableName = tableNameInter.value();

            //遍历类内变量
            Object o = cls.newInstance();
            Field[] declaredFields = o.getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);

                TableBean tableBean = new TableBean();

                //静态字段以及final字段略过
                int modifiers = field.getModifiers();
                if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) continue;

                //如果包含略过的注释这个字段不进行封装
                boolean isSetSkipField = field.isAnnotationPresent(NoSetSkipField.class);
                boolean isGetSkipField = field.isAnnotationPresent(NoGetSkipField.class);
                if (isSetSkipField && isGetSkipField) continue;

                TableField tableField = field.getAnnotation(TableField.class);
                tableBean.name = field.getName();
                //获取字段名称,如果存在注释使用注释的名称
                if (tableField != null) {
                    if (!StringUtils.isEmpty(tableField.value())) {
                        tableBean.name = tableField.value();
                    }
                    if (tableField.isKey()) {
                        tableBean.isKey = true;
                    }
                }

                //获取字段类型
                String classType = field.getType().toString();
                int lastIndex = classType.lastIndexOf(".");
                classType = classType.substring(lastIndex + 1);

                switch (classType) {
                    case "String" :
                        if (tableField != null) {
                            if (tableField.length() == 0 || tableField.length() > 255) {
                                tableBean.type = TableBean.TEXT;
                            } else {
                                tableBean.type = TableBean.CHAR;
                                tableBean.length = tableField.length();
                            }
                        } else {
                            tableBean.type = TableBean.TEXT;
                        }
                        break;
                    case "int" :
                    case "long" :
                    case "boolean" :
                        tableBean.type = TableBean.INT;
                        break;
                    case "Date" :
                        tableBean.type = TableBean.DATETIME;
                        break;
                    case "Double" :
                    case "Float" :
                        tableBean.type = TableBean.DOUBLE;
                        break;
                    default:
                        tableBean.type = TableBean.TEXT;
                }
                tableBeans.add(tableBean);
            }
        } else {
            LogUtils.e(TAG, "getCreateTableData() 获取表名失败，创建本地数据表失败: " + "类不包含TableName注释");
        }
        return new Pair<>(tableName,tableBeans);
    }

    /**
     * 存入数据库
     * 获取相对与数据库的字段名和字段值
     * 只支持5种基本类型
     * */
    public static ContentValues beanToSql(Object object){
        Field[] fields = object.getClass().getDeclaredFields();
        ContentValues contentValues = new ContentValues();
        for (Field field : fields) {
            field.setAccessible(true);

            //静态字段以及final字段略过
            int modifiers = field.getModifiers();
            if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) continue;

            //如果包含略过的注释这个字段不进行封装
            boolean isSkipField = field.isAnnotationPresent(NoSetSkipField.class);
            if (isSkipField) continue;

            String value;
            String annotation;
            annotation = field.getName();
            boolean isHaveIn = field.isAnnotationPresent(TableField.class);
            if (isHaveIn) {
                TableField name = field.getAnnotation(TableField.class);
                if (name != null)  {
                    if (!StringUtils.isEmpty(name.value())) {
                        annotation = name.value();
                    }
                }
            }

            String classType = field.getType().toString();
            int lastIndex = classType.lastIndexOf(".");
            classType = classType.substring(lastIndex + 1);

            if (classType.equals("String") || classType.equals("int") || classType.equals("long") || classType.equals("Date") ||
                    classType.equals("Double") || classType.equals("boolean") || classType.equals("String;")) {
                try {
                    value = String.valueOf(field.get(object));
                    if (StringUtils.isEmpty(value)) continue;
                    if (classType.equals("String")) contentValues.put(annotation, value);
                    if (classType.equals("int")) contentValues.put(annotation, Integer.parseInt(value));
                    if (classType.equals("long")) contentValues.put(annotation, Long.parseLong(value));
                    if (classType.equals("Date")) contentValues.put(annotation, value);
                    if (classType.equals("Double")) contentValues.put(annotation, Double.parseDouble(value));
                    if (classType.equals("boolean")) contentValues.put(annotation, Boolean.parseBoolean(value));
                    if (classType.equals("String;")) {
                        String[] ioo = (String[]) field.get(object);
                        contentValues.put(annotation, StringUtils.arrayToString(ioo));
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }
        LogUtils.d("转换：",JSON.toJSONString(contentValues));
        return contentValues;
    }

    /**
     * 存入数据库
     * 获取相对与数据库的字段名和字段值
     * 只支持5种基本类型
     * */
    public static Pair<String,ContentValues> beanToSqlNameAndData(Object object){
        String tableName = null;
        Field[] fields = object.getClass().getDeclaredFields();
        ContentValues contentValues = new ContentValues();
        Class<?> aClass = object.getClass();
        TableName tableNameInter = aClass.getAnnotation(TableName.class);
        if (tableNameInter != null) {
            tableName = tableNameInter.value();
        }
        for (Field field : fields) {
            field.setAccessible(true);

            //静态字段以及final字段略过
            int modifiers = field.getModifiers();
            if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) continue;

            //如果包含略过的注释这个字段不进行封装
            boolean isSkipField = field.isAnnotationPresent(NoSetSkipField.class);
            if (isSkipField) continue;

            String value;
            String annotation;
            annotation = field.getName();
            boolean isHaveIn = field.isAnnotationPresent(TableField.class);

            boolean isKey = false;
            if (isHaveIn) {
                TableField name = field.getAnnotation(TableField.class);

                if (name != null)  {
                    if (!StringUtils.isEmpty(name.value())) {
                        annotation = name.value();
                    }
                    if (name.isKey()) isKey = true;
                }
            }

            String classType = field.getType().toString();
            int lastIndex = classType.lastIndexOf(".");
            classType = classType.substring(lastIndex + 1);

            if (classType.equals("String") || classType.equals("int") || classType.equals("long") || classType.equals("Date") ||
                    classType.equals("Double") || classType.equals("boolean") || classType.equals("String;")) {
                try {
                    value = String.valueOf(field.get(object));
                    if (StringUtils.isEmpty(value)) continue;
                    if (classType.equals("String")) contentValues.put(annotation, value);
                    if (classType.equals("int"))  {
                        int i = Integer.parseInt(value);
                        //当前数值类型字段是key并且值为0略过
                        if (i==0 && isKey) {
                            continue;
                        } else {
                            contentValues.put(annotation, Integer.parseInt(value));
                        }
                    }

                    if (classType.equals("long"))  {
                        long i = Long.parseLong(value);
                        //当前数值类型字段是key并且值为0略过
                        if (i==0 && isKey) {
                            continue;
                        } else {
                            contentValues.put(annotation, Long.parseLong(value));
                        }
                    }

                    if (classType.equals("Date")) contentValues.put(annotation, value);
                    if (classType.equals("Double")) contentValues.put(annotation, Double.parseDouble(value));
                    if (classType.equals("boolean")) contentValues.put(annotation, Boolean.parseBoolean(value));
                    if (classType.equals("String;")) {
                        String[] ioo = (String[]) field.get(object);
                        contentValues.put(annotation, StringUtils.arrayToString(ioo));
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
//        LogUtil.d("转换：",JSON.toJSONString(contentValues));
        return new Pair<>(tableName,contentValues);
    }



    /**
     * 根据数据库返回的数据生成bean返回
     * 只支持5种基本类型
     * */
    public  static <T> List<T> sqlToListBean(Class<T> cls, ArrayList<HashMap<String, String>> data){
        Field[] fields = cls.getDeclaredFields();
        List<T> list = new ArrayList<>();
        Map<String, FieldInfo> map = new HashMap<>();

        //遍历字段获取字段数据
        for (Field field : fields) {

            //静态字段以及final字段略过
            int modifiers = field.getModifiers();
            if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) continue;

            String annotation = field.getName();
            field.setAccessible(true);
            FieldInfo fieldInfo = new FieldInfo();
            boolean isHaveIn = field.isAnnotationPresent(TableField.class);
            //如果有注释获取注释的名称
            if (isHaveIn) {
                TableField name = field.getAnnotation(TableField.class);
                if (name != null)  {
                    if (!StringUtils.isEmpty(name.value())) {
                        annotation = name.value();
                    }
                }
            }
            String classType = field.getType().toString();
            int lastIndex = classType.lastIndexOf(".");
            classType = classType.substring(lastIndex + 1);
            fieldInfo.type = classType;
            fieldInfo.name = annotation;
            fieldInfo.field = field;
//            LogUtil.d("反射输出：",annotation+"---"+classType);
            map.put(annotation,fieldInfo);
        }

        try {
            //便利传入的数据
            for (HashMap<String, String> datum : data) {
                Object object = cls.newInstance();
                //遍历字段
                for (String key : map.keySet()) {
                    //如果传入的数据里包含该字段，将值赋给该字段
                    if (datum.containsKey(key)) {
                        FieldInfo fieldInfo = map.get(key);
                        String str = datum.get(key);
                        if (fieldInfo != null && str != null) {
                            //各种类型数据的处理
                            if (fieldInfo.type.equals("int")) {
                                fieldInfo.field.set(object,Integer.parseInt(str));
                            }
                            if (fieldInfo.type.equals("long")) {
                                fieldInfo.field.set(object,Long.parseLong(str));
                            }
                            if (fieldInfo.type.equals("Date")) {
                                fieldInfo.field.set(object,str);
                            }
                            if (fieldInfo.type.equals("Double")) {
                                fieldInfo.field.set(object,Double.parseDouble(str));
                            }
                            if (fieldInfo.type.equals("boolean")) {
                                fieldInfo.field.set(object,Boolean.parseBoolean(str));
                            }
                            if (fieldInfo.type.equals("String")) {
                                fieldInfo.field.set(object,str);
                            }
                            if (fieldInfo.type.equals("String;")) {
                                String[] array = str.split(",");
                                fieldInfo.field.set(object,array);
                            }
                        }
                    }
                }
                list.add(cls.cast(object));
            }

        } catch (IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        return list;
    }



}
